package com.changjiang.luban.utils.dao;


import com.changjiang.luban.utils.ContrastUtils;
import com.changjiang.luban.utils.ConvertUtil;
import com.changjiang.luban.utils.StringUtils;
import com.changjiang.luban.utils.data.Page;
import org.hibernate.SQLQuery;
import org.hibernate.transform.Transformers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;

import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;

/**
 * 描述:自定义BaseRepository接口的实现
 * @author nichangjiang@vip.qq.com
 * 创建时间:2017/11/24 17:17
 * 修改人:nichangjiang@vip.qq.com
 * 修改时间: 2017/11/24 17:17
 * 修改备注:
 * 版本:v1.0
 */
public class BaseDaoImpl<T, ID extends Serializable> extends SimpleJpaRepository<T,ID>
        implements BaseDao<T,ID> {

    Logger log = LoggerFactory.getLogger(this.getClass());

    private final EntityManager entityManager;

    /**
     * 父类没有不带参数的构造方法，这里手动构造父类
     */
    public BaseDaoImpl(Class<T> domainClass, EntityManager entityManager) {
        super(domainClass, entityManager);
        this.entityManager = entityManager;
    }

    /**
     * 新增对象
     * @param entity 对象实体
     * @return
     */
    @Override
    public boolean saveEntity(T entity) {
        T newEntity = super.save(entity);
        return !ContrastUtils.isNull(newEntity);
    }

    /**
     * 更新对象
     * @param entity 对象实体
     * @return true 更新成功  false 更新失败
     */
    @Override
    public boolean update(T entity) {
        boolean flag = false;
        try {
            entityManager.merge(entity);
            flag = true;
        }catch (Exception e){
            log.error("实体更新失败");
        }
        return flag;
    }

    /**
     * 删除实体对象
     *
     * @param entity 对象实体
     * @return true 删除成功  false 删除失败
     */
    @Override
    public boolean deleteEntity(T entity) {
        boolean flag=false;
        try {
            entityManager.remove(entityManager.merge(entity));
            flag=true;
        }catch (Exception e){
            log.error("删除实体出现错误");
        }
        return flag;
    }

    @Override
    public Integer sum(String sql) {
        try{
            Query query = entityManager.createNativeQuery(sql);
            if(ContrastUtils.isNull(query.getSingleResult())){
                return 0;
            }
            return Integer.parseInt(( query.getSingleResult()).toString());
        }catch (Exception e){
            e.printStackTrace();
            log.error("查询结果记录数出现异常,查询SQL----->"+sql);
        }
        return 0;
    }

    @Override
    public Object get(String sql, Class<?> clazz) {
        List rowList = list(sql,clazz);
        if(rowList.size()>0){
            return rowList.get(0);
        }
        return null;
    }

    @Override
    public List list(String sql, Class<?> clazz) {
        try {
            Query query = entityManager.createNativeQuery(sql);
            query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
            List<Map<String, Object>> queryResultList =  query.getResultList();
            List<?> rowList;
            if(clazz != null){
                rowList = ConvertUtil.convertList(clazz,queryResultList);
            }else {
                rowList = queryResultList;
            }
            return rowList;
        }catch (Exception e){
            e.printStackTrace();
            log.error("分页查询出现错误,查询SQL----->"+sql);
            return null;
        }
    }


    /**
     * @param page
     * @param nameQuery
     * @return
     */
    @Override
    public Page page(Page page, String nameQuery) {
        return null;
    }

    /**
     * 分页查询接口
     *
     * @param sql    查询SQL
     * @param page   分页对象
     * @return Page 分页对象
     */
    @Override
    public Page page(String sql,Page page,Class<?> clazz) {
        return page(sql,null,page,clazz);
    }

    /**
     * 分页查询接口
     * @param sql    查询SQL
     * @param params 查询参数
     * @param page   分页对象
     * @return Page 分页对象
     */
    @Override
    @SuppressWarnings("unchecked")
    public Page page(String sql,Map<String, Object> params, Page page,Class<?> clazz) {
        try {
            Query query = entityManager.createNativeQuery(sql);
            Integer rowCount =  getResultCount(sql);
            if(rowCount>0){
                if(params!=null){
                    for (String key : params.keySet()) {
                        query.setParameter(key, params.get(key));
                    }
                }
                query.setFirstResult(page.getSize() * (page.getIndex()-1));
                query.unwrap(SQLQuery.class).setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
                query.setMaxResults(page.getSize());
                List<Map<String, Object>> queryResultList =  query.getResultList();
                List<?> rowList = null;
                if(queryResultList.size()>0){
                    if(clazz != null){
                        rowList = ConvertUtil.convertList(clazz,queryResultList);
                    }else {
                        rowList = queryResultList;
                    }
                }
                page.setRowCount(rowCount);
                page.setRowList(rowList);
            }else{
                page.setRowCount(rowCount);
                page.setRowList(null);
            }
            return page;
        }catch (Exception e){
            e.printStackTrace();
            log.error("分页查询出现错误,查询SQL----->"+sql);
            return null;
        }
    }

    /**
     * 查询结果记录数
     * @param sql 查询SQL
     * @return 记录数
     */
    @Override
    public Integer getResultCount(String sql) {
        try{
            sql = StringUtils.sqlToCountSql(sql);
            if(ContrastUtils.isNull(sql)){
                Query query = entityManager.createNativeQuery(sql);
                return ((BigInteger) query.getSingleResult()).intValue();
            }
        }catch (Exception e){
            e.printStackTrace();
            log.error("查询结果记录数出现异常,查询SQL----->"+sql);
        }
        return 0;
    }



}
